/*
 * @Description: 排序信息面板
 * @Author: Rfan
 * @Date: 2022-02-10 09:30:53
 * @LastEditTime: 2023-01-12 16:27:21
 */

import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import classNames from 'classnames/bind';
import { Alert, Button, Space, Table, Tag } from 'antd';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
import { useSortContext } from '../contexts/SortContext';
import { useFormatMessage } from '@/utils/intlHelpers';
import { getListItemValue } from '@/utils/list';
import DraggableBodyRow from '@/components/DraggableBodyRow';
import AddDialog from './dialogs/AddDialog';
import EditDialog from './dialogs/EditDialog';
import styles from '../styles/sortPane.module.scss';

const cx = classNames.bind(styles);

const { Column } = Table;

export type SortPaneProps = {
  title?: string;
  data?: any;
};

const SortPane: FC<SortPaneProps> = (props) => {
  const { title, data } = props;
  const formatMessage = useFormatMessage();
  const {
    list,
    loading,
    sortType,
    selectLevel,
    selectItems,
    initListQuery,
    initTable,
    setSelectKey,
    setList,
    deleteSortingFunc,
    updateSortFunc
  } = useSortContext();

  // 新增弹窗展示状态
  const [saveBtnLoading, setSaveBtnLoading] = useState(false);
  // 编辑弹窗展示状态
  const [addDialogVisible, setAddDialogVisible] = useState(false);
  // 编辑弹窗展示状态
  const [editDialogVisible, setEditDialogVisible] = useState(false);
  // 编辑的条目信息
  const [editData, setEditData] = useState({});

  useEffect(() => {
    initTable();
    initListQuery({ ...data });
  }, [data]);

  const showDialog = (): void => {
    setAddDialogVisible(true);
  };

  // 表格选项相关设置
  const onSelectChange = (selectedKeys: number[]): void => {
    setSelectKey(selectedKeys);
  };

  const rowSelection = {
    selectItems,
    onChange: onSelectChange
  };

  const delSorting = (id: number): void => {
    deleteSortingFunc(id, '确认删除该排序？');
  };

  /**
   * 拖拽相关
   */
  const components = {
    body: {
      row: DraggableBodyRow
    }
  };

  const moveRow = useCallback(
    (dragIndex, hoverIndex) => {
      const dragRow = list[dragIndex];
      // 更新数据
      setList(
        update(list, {
          $splice: [
            [dragIndex, 1],
            [hoverIndex, 0, dragRow]
          ]
        })
      );
    },
    [list]
  );

  /**
   * @description: 保存排序
   */
  const saveSort = () => {
    setSaveBtnLoading(true);
    const sortRule = list.map((item: any, idx: number) => {
      const ele: any = item.rule;
      ele.sortNo = idx + 1;
      return ele;
    });
    updateSortFunc(sortRule).finally(() => {
      setSaveBtnLoading(false);
    });
  };

  const showEditDialog = (data: any) => {
    setEditData(data);
    setEditDialogVisible(true);
  };

  return (
    <div className={cx('sort-pane')}>
      <div className={cx('sort-header')}>
        <div className={cx('title')}>{title}排序</div>
        <div className={cx('operate')}>
          <Space>
            <Button
              disabled={!selectLevel || JSON.stringify(selectLevel) === '{}'}
              onClick={showDialog}
            >
              新建排序字段
            </Button>
            <Button
              disabled={selectItems.length <= 0}
              onClick={() => {
                deleteSortingFunc(selectItems);
              }}
            >
              删除排序字段
            </Button>
            <Button type="primary" loading={saveBtnLoading} onClick={saveSort}>
              保存排序
            </Button>
          </Space>
        </div>
      </div>
      <div className={cx('tips')}>
        <Alert
          description="备注：调整排序可在表单内使用鼠标拖动“行”来实现；也可使用功能弹窗调整排序号（越小越靠前）"
          type="info"
          showIcon
          closable
        />
      </div>
      <div className={cx('container')}>
        <DndProvider backend={HTML5Backend}>
          <Table
            dataSource={list}
            loading={loading}
            rowKey={(record) => record.rule.id}
            pagination={false}
            rowSelection={rowSelection}
            components={components}
            bordered
            onRow={(_record, index) =>
              ({
                index,
                moveRow
              } as any)
            }
          >
            <Column
              title="序号"
              dataIndex={['rule', 'id']}
              key="id"
              align="center"
              render={(_text, _record, index: number) => <span>{index + 1}</span>}
            />
            <Column title="排序" dataIndex={['rule', 'sortNo']} key="sortNo" align="center" />
            <Column
              title="字段名称"
              dataIndex={['field', 'field_desc']}
              key="fieldDesc"
              align="center"
            />
            <Column
              title="排序方式"
              dataIndex={['rule', 'sortType']}
              key="sortType"
              align="center"
              render={(text) => (
                <Tag color={getListItemValue(text, sortType, 'color')}>
                  {getListItemValue(text, sortType)}
                </Tag>
              )}
            />
            <Column
              title={formatMessage('tableAction')}
              key="action"
              align="center"
              render={(_text, record: any) => (
                <Space>
                  <Button
                    type="link"
                    onClick={() => {
                      showEditDialog(record);
                    }}
                  >
                    编辑
                  </Button>
                  <Button type="link" danger onClick={() => delSorting(record.rule.id)}>
                    删除
                  </Button>
                </Space>
              )}
            />
          </Table>
        </DndProvider>
      </div>
      {useMemo(
        () => (
          <AddDialog
            visible={addDialogVisible}
            onClose={() => {
              setAddDialogVisible(false);
            }}
          />
        ),
        [addDialogVisible]
      )}
      {useMemo(
        () => (
          <EditDialog
            visible={editDialogVisible}
            data={editData}
            onClose={() => {
              setEditDialogVisible(false);
            }}
          />
        ),
        [editDialogVisible]
      )}
    </div>
  );
};

export default SortPane;
